home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 1.iso
/
ARGONET
/
PD
/
DESKTOP
/
MYMENU.ZIP
/
Sources
/
SourceScan
(
.txt
)
< prev
Wrap
RISC OS BBC BASIC V Source
|
1996-12-10
|
43KB
|
1,439 lines
Richard Atterer 1996
=0:sp=13:lr=14:
$" at line ";
/save$=":4.$.Coding.MyMenu.!MyMenu.ScanUtil"
type$="Utility"
,size%=7<<10:
code% size%:L%=code%+size%
debugging%=0
debugging%
"Lib:Debug2"
*washerefile$="<MyMenu$Dir>.^.IWasHere"
washerefile$="RAM:IWasHere"
private error numbers
Err_UnknownCommand=1
Err_WrongSpecial=2
Err_SpecExists=3
Err_SpecNotDef=4
Err_OutOfSpace=5
Err_ModUk=6
Err_ModB=7
Err_ModK=8
Err_ModL=9
Err_ModM=10
Err_MOnceOnly=11
Err_NoCLI=12
Err_EmptyMenu=13
Err_NoKeys=14
Err_WrongCommPos=15
Err_DoubleKey=16
!code%=3:
"OS_Word",14,code%:
"Territory_ConvertDateAndTime",1,code%,code%+8,256,"%DY %M3 %CE%YR"
,A%:d$="":
B%=code%+8
A%-1:d$=d$+
p%=12
2:O%=code%:P%=0
:p=p%:
B%,B%,C%:
p%=14
C%>0 p=p%
$ [optp
%-;________________________________________
;format of "menu" RMA block
;--------------------------
;for each menu:
*@; 4 width of menu items (when displaying with system font)
+ ; 4 number of menu items=N
;16*N items
;for each item:
.=; 4 number of submenu (invisible main menu has nr 0) or
/*; (offset of *commands)
1<<31, or
0+; (file offset of *commands)
1<<30
16; bit 28 set indicates icon data is indirected
; 12 menu icon data
3D; if not indirected; 12 text, up to 12 chars, padded with 0s
4C; if indirected; 4 offset of text in "indir" RMA block
5L; 4 -1 (or offset of "Sxxxxx" validation string)
6J; 4 length of text incl. terminator (a 0 byte)
7P;"indir" RMA block contains a number of strings, either indirected item text
;or buffered *commands
:6;format of hotkeys (stored downwards from R12+896)
;-----------------
<D; 4 key(s) with 1st key in bits 24-31, 2nd in bits 16-23 etc.
=0; 4 bits 0-1 = nr of keys in 1st word - 1
>-; bits 2-17 = nr of item inside menu
?"; bits 18-30 = nr of menu
@K; bit 31 set to make sure value is non-zero (needed by the module)
AK; (the word stored in "mouse" is the same format as this 2nd word)
CJ;Note - this whole utility doesn't contain very optimized code because
;that's not necessary...
E-;______...____________________;__________
.utilstart
bic lr,lr,#1<<28
stmfd sp !,{lr}
debugging%
[optp
bl IWasHere_NewFile
adr r0,utilstart
d("address of executable=^0^"):]
:[optp
mov r0,#0
mov r1,#var_end-4
.clearvars
str r0,[r12,r1]
subs r1,r1,#4
bpl clearvars
mvn r0,#0
str r0,[r12,#sourceh]
str r0,[r12,#desth]
add r0,r12,#896
str r0,[r12,#hotkey]
;open source
mov r0,#&4F
adr r1,menufile
swi "XOS_Find"
bvs error
str r0,[r12,#sourceh]
;open destination
;mov r0,#&8F
;adr r1,scanfile
;swi "XOS_Find"
;bvs error
;str r0,[r12,#desth]
nB;claim extra workspace (initially 4k each, but may grow later)
mov r0,#6
mov r3,#4<<10
swi "XOS_Module"
bvs error
str r2,[r12,#menu]
str r3,[r12,#menusize]
mov r1,#0
str r1,[r2]
str r1,[r2,#4]
mov r1,#8
str r1,[r12,#menuused]
mov r3,#4<<10
swi "XOS_Module"
bvs error
str r2,[r12,#indir]
str r3,[r12,#indirsize]
;____________
,.scanloop ;MAIN LOOP
bl getstring
bvs endloop
M;ldr r2,[r12,#stringstart] ;strip any leading spaces/tabs from string
;sub r2,r2,#1
;.scanloop1
;ldrb r0,[r2,#1]!
;teq r0,#9
;teqne r0,#32
;beq scanloop1
!;str r2,[r12,#stringstart]
;____________
.scanloop2
;adr r1,specialstr ;special char definition?
bl stringstarteq
teq r0,#0
'bne scanloop3 ;nope
ldrb r0,[r12,#special]
;teq r0,#0 ;special already defined?
movne r3,#Err_SpecExists
,bne report ;y > error
ldr r2,[r12,#stringstart]
ldr r3,[r12,#stringend]
sub r1,r3,r2
Oteq r1,#9 ;is there just one char after the "Special" ?
-movne r3,#Err_WrongSpecial ;no > error
bne report
?ldrb r0,[r2,#8] ;r0=
II value of special char
strb r0,[r12,#special]
b scanloop
+.menufile dcb"<MyMenu$M>.Menu":dcb0
$.specialstr dcb"Special:":dcb0
+.bufferallstr dcb"BufferAll":dcb10:dcb0
4.ondemandstr dcb"LoadOnDemand":dcb10:dcb0:align
-;________________________________________
.scanloop3
Ladr r1,bufferallstr ;buffer all *commands (ignore B modifier)?
bl stringstarteq
teq r0,#0
'bne scanloop4 ;nope
d("BufferAll")
ldr r0,[r12,#menuused]
teq r0,#8
mov r3,#Err_WrongCommPos
bne report
3strb r3,[r12,#bufferallinit] ;is non-zero now
b scanloop
-;________________________________________
.scanloop4
Qadr r1,ondemandstr ;load MenuScan file only when hotkey is pressed?
bl stringstarteq
teq r0,#0
'bne scanloop5 ;nope
ldr r0,[r12,#menuused]
d("LoadOnDemand")
teq r0,#8
mov r3,#Err_WrongCommPos
bne report
mvn r0,#0
/strb r3,[r12,#ondemand] ;non-zero now
#;strb r3,[r12,#bufferallinit]
b scanloop
-;________________________________________
;r9=indir
;r10=current string ptr
;r11=special
.scanloop5
ldrb r11,[r12,#special]
;teq r11,#0 ;special already defined?
moveq r3,#Err_SpecNotDef
beq report
ldr r9,[r12,#indir]
!ldr r10,[r12,#stringstart]
ldrb r0,[r10],#1
'teq r0,r11 ;"*"?
bne syntaxerror
ldrb r0,[r10],#1
(teq r0,r11 ;"**"?
bne entry
;____________
Q;search for the specified "menu path" - if any menus don't exist, create them
E;r0=current menu, r1=current item, r2=items left in current menu,
5;r3=submenu levels left (during search for menus)
.menucommand
d("menucommand")
mov r0,r10
Pmov r3,#0 ;r3=nr of "*"s in this line after initial "**"
.menu1
ldrb r1,[r0],#1
teq r1,r11
addeq r3,r3,#1
teq r1,#10
bne menu1
teq r3,#0
beq syntaxerror
ldr r0,[r12,#menu]
9.menu2 ;r0=ptr to current menu
add r1,r0,#8
ldmib r0,{r2}
H.menu3 ;r1=ptr to current item, r2=items left
subs r2,r2,#1
>bmi menu_create ;not found > create new menu
ldmia r1!,{r4-r7}
<tst r4,#3<<30 ;is this a submenu number?
0bne menu3 ;n > next item
mov r8,r10
6tst r4,#1<<28 ;is data indirected?
Faddne r5,r9,r5 ;y > calc string address from offset
$subeq r5,r1,#12 ;n
Gmoveq r7,#13 ;n (length incl IMAGINARY terminator)
Q;at this point for both indirected and not, r5=ptr to string, r7=max length+1
I.menu4 ;compare submenu's name with our string
ldrb r14,[r8],#1
teq r14,r11
=moveq r14,#0 ;special char is terminator
subs r7,r7,#1
ldrneb r6,[r5],#1
Nmoveq r6,#0 ;important for non-indir. icons of length 12
teq r14,r6
>bne menu3 ;not same string > next item
,teq r14,#0 ;finished?
bne menu4
/;found submenu item with our string as name
d("menu^^submenu with name found")
bic r4,r4,#3<<28
4subs r3,r3,#1 ;further submenus?
!streq r1,[r12,#leafmenuitem]
streq r4,[r12,#entrymenu]
$beq menu_modifiers ;n
?.menu5 ;NB r4 is still nr of submenu
ldr r0,[r12,#menu]
.menu6
Kldmia r0!,{r1-r2} ;load of r1 not necessary, but never mind
9add r0,r0,r2,lsl#4 ;16 bytes for each item
subs r4,r4,#1
bne menu6
Imov r10,r8 ;r10 now ptr to string for next submenu
b menu2
;____________
O;one of the menus specified didn't exist, so now create it and also further
;submenus inside it, if any
.menu_create
d("menu^^create new submenu - current menu=^0^")
!Lldr r1,[r12,#nrofmenus] ;first append submenu item to current menu
add r1,r1,#1
str r1,[r12,#nrofmenus]
str r1,[r12,#entrymenu]
sub r8,r10,#1
.menu_create1
ldrb r2,[r8,#1]!
teq r2,r11
bne menu_create1
bl insertnewitem
,=ldmia r0!,{r2,r4} ;r2 not needed - never mind
add r2,r0,r4,lsl#4
.Nstr r2,[r12,#leafmenuitem] ;no need for offset - no mem claims from now
0P;create the new menu - NB 8 bytes space have been allocated by insertnewitem
ldr r0,[r12,#menu]
mov r2,#0
ldr r4,[r12,#menuused]
add r0,r0,r4
5Msub r1,r1,#16 ;=min item width for a title of this length
stmia r0,{r1-r2}
add r4,r4,#8
str r4,[r12,#menuused]
add r10,r8,#1
;1subs r3,r3,#1 ;more submenus?
<Qbne menu_create ;y > don't search because current menu is empty
=Padd r8,r8,#1 ; instead, create any further submenus imm.
;____________
@+;r8=ptr to tail of line, with modifiers
AP.menu_modifiers ;interpretation of eg B;Kxx;L at end of string
B"ldrb r0,[r12,#bufferallinit]
strb r0,[r12,#bufferall]
.menu_mod
teq r0,#10
beq scanloop
.menu_mod1
ldrb r0,[r8],#1
teq r0,#10
beq scanloop
N+teq r0,#
"b" ;B modifier
teqne r0,#
bne menu_mod2
d("menu^^B modifier")
ldrb r0,[r8],#1
teq r0,#
teqne r0,#10
movne r3,#Err_ModB
bne report
W0strb r0,[r12,#bufferall] ;just non-zero
b menu_mod
Z-.menu_mod2 ;L modifier
teq r0,#
teqne r0,#
bne menu_mod3
d("menu^^L modifier")
ldrb r0,[r8],#1
teq r0,#
teqne r0,#10
movne r3,#Err_ModL
bne report
d!ldr r1,[r12,#leafmenuitem]
ldr r2,[r1,#-16]
orr r2,r2,#1<<29
str r2,[r1,#-16]
b menu_mod
j-.menu_mod3 ;M modifier
teq r0,#
teqne r0,#
bne menu_mod5
ldrb r0,[r8],#1
d("menu^^M modifier")
teq r0,#
teqne r0,#10
movne r3,#Err_ModM
bne report
ldr r3,[r12,#mouse]
teq r3,#0
movne r3,#Err_MOnceOnly
bne report
ldr r1,[r12,#menu]
z!ldr r7,[r12,#leafmenuitem]
mov r4,#0
|B.menu_mod4 ;search for "leafmenuitem"s menu
ldmia r1!,{r5-r6}
add r1,r1,r6,lsl#4
cmp r1,r7
addlo r4,r4,#1
blo menu_mod4
sub r1,r1,r6,lsl#4
mov r3,r4,lsl#18
sub r4,r7,r1
sub r4,r4,#16
orr r3,r3,r4,lsr#4-2
-orr r3,r3,#1<<31 ;set bit 31
str r3,[r12,#mouse]
b menu_mod
-.menu_mod5 ;K modifier
teq r0,#
teqne r0,#
movne r3,#Err_ModUk
bne report
d("menu^^K modifier")
mov r0,#16
mov r1,r8
swi "XOS_ReadUnsigned"
movvs r3,#Err_ModK
bvs report
sub r3,r1,r8
movs r3,r3,lsr#1
movcs r3,#Err_ModK
=bcs report ;need even number of digits
sub r3,r3,#1
ldr r0,[r12,#menu]
!ldr r7,[r12,#leafmenuitem]
mov r4,#0
B.menu_mod6 ;search for "leafmenuitem"s menu
ldmia r0!,{r5-r6}
add r0,r0,r6,lsl#4
cmp r0,r7
addlo r4,r4,#1
blo menu_mod6
sub r0,r0,r6,lsl#4
orr r3,r3,r4,lsl#18
sub r4,r7,r0
sub r4,r4,#16
orr r3,r3,r4,lsr#4-2
bl hotkeyentry
mov r8,r1
ldrb r0,[r8],#1
teq r0,#
teqne r0,#10
movne r3,#Err_ModK
bne report
b menu_mod
-;________________________________________
.entry
sub r10,r10,#1
>ldr r5,[r12,#menu] ;find menu to place entry in
ldr r4,[r12,#entrymenu]
d("entry^^entrymenu=^4^")
mov r0,r4
.entry1
subs r0,r0,#1
ldmgeiar5!,{r2-r3}
addge r5,r5,r3,lsl#4
bge entry1
3ldr r8,[r12,#stringend] ;find end of line
.entry2
ldrb r0,[r8,#-1]!
teq r0,r11
bne entry2
ldrb r6,[r12,#bufferall]
teq r6,#0
moveq r6,#1<<31
movne r6,#1<<30
add r7,r8,#1
mov r1,#0
;______
.entry_mod
teq r1,#10
beq entry3
.entry_mod1
ldrb r1,[r7],#1
teq r1,#10
beq entry3
+teq r1,#
"b" ;B modifier
teqne r1,#
bne entry_mod2
d("entry^^B modifier")
ldrb r1,[r7],#1
teq r1,#
teqne r1,#10
movne r3,#Err_ModB
bne report
bic r6,r6,#1<<31
orr r6,r6,#1<<30
b entry_mod
-.entry_mod2 ;L modifier
teq r1,#
teqne r1,#
bne entry_mod3
d("entry^^L modifier")
ldrb r1,[r7],#1
teq r1,#
teqne r1,#10
movne r3,#Err_ModL
bne report
orr r6,r6,#1<<29
b entry_mod
-.entry_mod3 ;M modifier
teq r1,#
teqne r1,#
bne entry_mod4
d("entry^^M modifier")
ldrb r1,[r7],#1
teq r1,#
teqne r1,#10
movne r3,#Err_ModM
bne report
ldr r3,[r12,#mouse]
teq r3,#0
movne r3,#Err_MOnceOnly
bne report
mov r3,r4,lsl#18
ldmib r5,{r0}
orr r3,r3,r0,lsl#2
-orr r3,r3,#1<<31 ;set bit 31
str r3,[r12,#mouse]
b entry_mod
-.entry_mod4 ;K modifier
teq r1,#
teqne r1,#
movne r3,#Err_ModUk
bne report
d("menu^^K modifier")
mov r0,#16
mov r1,r7
swi "XOS_ReadUnsigned"
movvs r3,#Err_ModK
bvs report
sub r3,r1,r7
movs r3,r3,lsr#1
movcs r3,#Err_ModK
=bcs report ;need even number of digits
sub r3,r3,#1
orr r3,r3,r4,lsl#18
ldmib r5,{r0}
orr r3,r3,r0,lsl#2
bl hotkeyentry
mov r7,r1
ldrb r1,[r7],#1
teq r1,#
teqne r1,#10
movne r3,#Err_ModK
bne report
b entry_mod
;______
.entry3
)Ftst r6,#1<<31 ;*commands to be buffered in memory?
beq entry4
+$mov r0,#0 ;n
ldr r1,[r12,#sourceh]
swi "XOS_Args"
bvs error
orr r6,r6,r2
.entry4
mov r0,r5
mov r1,r6
bl insertnewitem
tst r6,#1<<31
bne entry10
ldmia r0!,{r1-r2}
add r0,r0,r2,lsl#4
ldr r1,[r12,#indirused]
ldr r2,[r0,#-16]
orr r2,r2,r1
str r2,[r0,#-16]
.entry10
bl getstring
movvs r3,#Err_NoCLI
@ ldrvc r1,[r12,#stringstart]
bvs report
ldrb r0,[r1],#-1
teq r0,r11
moveq r3,#Err_NoCLI
beq report
tst r6,#1<<31
bne entry8
;______
d("*command to be buffered in memory")
K@mov r0,#13 ;*comms 2 B buffered in memory
add r2,r12,#indir
ldmia r2,{r2,r8-r9}
.entry5
add r10,r1,#1
add r5,r2,r9
ldr r7,[r12,#stringend]
sub r6,r7,r10
SNsub r4,r5,#8<<10 ;8k limit when searching for matching *comms
cmp r4,r2
movlo r4,r2
bl indirmatch
subcs r7,r7,r1
bcs entry12
add r4,r2,r9
sub r4,r4,r5
d("entry5^^0=^0^, 1=^1^, 2=^2^, ^4^ bytes ago=^5^, 6=^6^, 10=^10^")
d("entry^^match ^4^ bytes ago")
]Mstrb r4,[r1,#2] ;NB hi-lo and not lo-hi, to ensure that the
^;mov r4,r4,lsr#8 ;first byte is always <32
strb r4,[r1,#1]
mov r4,#10
strb r4,[r1,#3]
mov r7,#3
;add r10,r2,#&ed0
;ldmib r10,{r3,r4}
d("entry^^at &ed4 ^4^ ^3^")
.entry12
d("entry12^^*comm of length ^7^ at ^1^")
add r9,r9,r7
jNsubs r3,r9,r8 ;sets the flags in the same way as cmp r9,r8
ble entry6
d("*2Bbuf before^^addr=^2^, size=^8^, new used=^9^, size needed=^7^")
add r3,r3,#&ff
n+bic r3,r3,#&ff ;round up
o3swi "XOS_Module" ;expand RMA block
bvs error
add r8,r8,r3
d("*2Bbuf after^^addr=^2^, size=^8^, used=^9^")
.entry6
add r4,r2,r9
sub r4,r4,r7
.entry7
ldrb r3,[r1,#1]!
strb r3,[r4],#1
subs r7,r7,#1
bne entry7
bl getstring
} ldrvc r1,[r12,#stringstart]
bvs entry11
ldrb r14,[r1],#-1
teq r14,r11
bne entry5
;______
mov r0,#0
<strb r0,[r4,#-1] ;to indicate last *command
add r0,r12,#indir
stmia r0,{r2,r8-r9}
b scanloop3
;____________
:.entry8 ;*comms not 2 B buffered
d("*commands not to be buffered")
ldr r2,[r12,#osclilen]
.entry9
ldr r6,[r12,#stringend]
sub r7,r6,r1
cmp r2,r7
movlt r2,r7
bl getstring
ldrvc r1,[r12,#stringstart]
str r2,[r12,#osclilen]
bvs endloop
ldrb r14,[r1],#-1
teq r14,r11
bne entry9
b scanloop3
-;________________________________________
.hotkeyentry
K;r2/r3=words to be placed in buffer for hotkeys (r3 bit 31 still unset)
stmfd sp !,{r4,lr}
orr r3,r3,#1<<31
ldr r0,[r12,#hotkey]
stmdb r0!,{r2-r3}
str r0,[r12,#hotkey]
P;sort key numbers in hotkey def's from lowest in byte 0 to highest in byte 3
mov r2,r0
add r0,r0,#3
P.hotkeyentry1 ;Quicksort-like, though not particularly quick
ldrb r3,[r2],#1
mov r4,r2
.hotkeyentry2
ldrb lr,[r4],#1
cmp r3,lr
strgtb r3,[r4,#-1]
movgt r3,lr
strgtb lr,[r2,#-1]
cmp r4,r0
bls hotkeyentry2
cmp r2,r0
blo hotkeyentry1
I;check if this hotkey combination has already been used - error if so
add r2,r12,#896
sub r0,r0,#3
ldr r3,[r0],#8
.hotkeyentry3
teq r0,r2
ldmeqfdsp !,{r4,pc}^
ldr r4,[r0],#8
teq r3,r4
bne hotkeyentry3
add sp,sp,#8
mov r3,#Err_DoubleKey
b report
-;________________________________________
.entry11
mov r0,#0
<strb r0,[r4,#-1] ;to indicate last *command
add r0,r12,#indir
stmia r0,{r2,r8-r9}
F;Yeee-Haaa! We've managed not to crash during interpretation, so -
; D O I T N O W . . . ?
.endloop
-; write the 'MenuScan' file in this form:
+; 4 total size of RMA block needed, ie
N; size of hotkey definitions + size of Wimp style menus + size of indir
(; 4 size of hotkeys (multiple of 8)
.; 4 length of largest unbuffered *command
/; 4 nr of menus (incl invisible main menu)
H; 1 zero for keeping menu in memory, non-zero for loading on demand
; 1 special character
; 2 zero bytes to align
?; 4 menu & icon nr of "M" modifier item - zero if not used
*; ? hotkey definitions (8 bytes each)
L; ? menu in Wimp format, ie can be passed to Wimp_CreateWindow once all
2; offsets have been replaced with addresses
; ? indirected data
J;NB all offsets in hotkey/menu data are relative to start of menu data
J;replace all submenu numbers with offsets from start of menu structure
=;assumes a menu header needs 32 bytes, each item needs 28
d("endloop^^will replace submenu items")
.; >>> WARNING! SPAGHETTI CODE FOLLOWS <<<
ldr r9,[r12,#hotkey]
sub r1,r9,r12
rsbs r8,r1,#896
ldreq r7,[r12,#mouse]
teqeq r7,#0
moveq r3,#Err_NoKeys
beq report
Jadd r7,r12,#string ;will store addresses of menu items here
ldr r11,[r12,#menu]
mov r0,r11
ldr r1,[r12,#nrofmenus]
0.endloop1 ;for each menu
ldmia r0!,{r2-r3}
7teq r3,#0 ;if no entries, error
moveq r3,#Err_EmptyMenu
beq report
0.endloop2 ;for each item
ldr r2,[r0],#16
:tst r2,#3<<30 ;is item a submenu item?
Ableq endloop_submenu ;y > replace number with offset
subs r3,r3,#1
bne endloop2
subs r1,r1,#1
bpl endloop1
;______
d("endloop^^will write to file")
mov r0,#&83
adr r1,scanfile
5swi "OS_Find" ;create output file
bvs error
str r0,[r12,#desth]
ldr r9,[r12,#nrofmenus]
add r9,r9,#1
mov r4,r9
mov r5,r9
ldr r2,[r12,#menuused]
5sub r10,r2,r5,lsl#3 ;r10=nr of items*16
rsb r2,r10,r10,lsl#3
4mov r2,r2,lsr#2 ;r2=nr of items*28
5add r2,r2,r5,lsl#5 ;r2+=nr of menus*32
mov r10,r2
add r1,r2,r8
ldr r5,[r12,#indirused]
add r1,r1,r5
mov r2,r8
ldr r3,[r12,#osclilen]
ldrb r5,[r12,#ondemand]
ldrb r6,[r12,#special]
orr r5,r5,r6,lsl#8
ldr r6,[r12,#mouse]
stmfd sp,{r1-r6}
6mov r1,r0 ;write 6 word header
mov r0,#2
sub r2,sp,#6<<2
mov r3,#6<<2
swi "XOS_GBPB"
bvs error
"<mov r0,#2 ;and write hotkeys to file
ldr r2,[r12,#hotkey]
mov r3,r8
swi "XOS_GBPB"
bvs error
(J;now write the menu data in Wimp format - each menu is preceded by the
):;additional info we need to store along with the items
*(; 4 A=number of items in this menu
+P; 4*A one word for each item, containing the submenu offset or (file) offset
; 28 Wimp menu header
;24*A Wimp menu items
.M;r10=constant added to offsets into indir (=size of wimp style menu data)
mov r0,r11
0Dadd r4,r12,#string ;r4=ptr to submenu items for menus
adr r2,maindummy+16
stmia r4,{r2}
.endloop7
ldmia r0!,{r2-r3}
5>mov r8,r3 ;write info before wimp menu
bl putword
mov r1,r0
mov r5,r3
.endloop8
ldr r8,[r1],#16
;Htst r8,#1<<30 ;is this a *command offset into indir?
<$addne r8,r8,r10 ;y
bl putword
subs r5,r5,#1
bne endloop8
ldmia r4!,{r5}
B2stmfd sp !,{r0,r3-r4} ;write wimp menu
ldr r1,wimpmenucol
mov r3,#44
mov r4,#0
FGstmfd sp !,{r1-r2,r3,r4} ;colours, width, height, vertical gap
ldr r6,[r5,#-16]
and r6,r6,#1<<28
movs r6,r6,lsr#28-8
ldmdb r5,{r0-r2}
K0addne r0,r0,r10 ;if indirected
L9stmfd sp !,{r0-r2} ;icon data of title bar
mov r0,#2
ldr r1,[r12,#desth]
mov r2,sp
mov r3,#28
swi "XOS_GBPB"
bvs error
add sp,sp,#28
ldmfd sp !,{r5,r7}
V8.endloop10 ;write wimp menu items
ldmia r5!,{r0-r2,r4}
tst r0,#1<<28
Y2addne r1,r1,r10 ;text indirected
Z,stmfd sp !,{r1-r2,r4} ;icon data
mov r1,r6
mov r6,#0
mov r2,r0
ldr r4,wimpmenuicon
tst r2,#1<<28
`2orrne r4,r4,#1<<8 ;text indirected
tst r2,#1<<29
b.orrne r1,r1,#1<<1 ;dotted line
c0tst r2,#3<<30 ;submenu item?
biceq r2,r2,#3<<28
e<mvnne r2,#0 ;n > submenu pointer is -1
teq r7,#1
g,orreq r1,r1,#1<<7 ;last item
hLbiceq r1,r1,#1<<1 ;last item never followed by a dotted line
stmfd sp !,{r1-r2,r4}
mov r0,#2
ldr r1,[r12,#desth]
mov r2,sp
mov r3,#24
swi "XOS_GBPB"
bvs error
add sp,sp,#24
subs r7,r7,#1
bne endloop10
ldmfd sp !,{r4}
subs r9,r9,#1
movne r0,r5
bne endloop7
;______
ldr r2,[r12,#indir]
ldr r3,[r12,#indirused]
|.swi "XOS_GBPB" ;write indir
bvs error
;______
mvn r0,#0
str r0,[r12,#desth]
mov r0,#0
-swi "XOS_Find" ;close file
bvs error
mov r0,#17
adr r1,menufile+1024+512
sub r1,r1,#1024+512
swi "XOS_File"
bvs error
Band r2,r2,#&ff ;important - preserve date stamp
Lldr r1,fileorr ;(MyMenu module uses this to make sure the
Eorr r2,r2,r1 ;MenuScan file is still up to date)
mov r0,#2
adr r1,scanfile
swi "XOS_File"
bvs error
mov r0,#3
adr r1,scanfile
swi "XOS_File"
bvs error
bl closedown
ldmvcfdsp !,{pc}^
ldmfd sp !,{lr}
orrs pc,lr,#1<<28
5.scanfile dcb"<MyMenu$M>.MenuScan":dcb0:align
.fileorr dcd &fffffd00
(.maindummy dcd0:dcb"InvisiblMain"
%.wimpmenucol dcb7:dcb2:dcb7:dcb0
4.wimpmenuicon dcd%000000110001
(7<<24)
(0<<28)
;____________
J;r2=nr of submenu, r4-r7 can be corrupted, r10=add, r11=menu, r14=link
.endloop_submenu
;mov r7,lr
d("endloop_submenu^^nr of submenu=^2^")
;mov lr,r7
and r4,r2,#3<<28
bic r2,r2,#3<<28
Nstr r0,[r7,r2,lsl#2] ;we'll use this later to find menus' parents
mov r5,r11
.endloop_submenu1
2add r4,r4,#32 ;for menu header
ldmib r5,{r6}
add r5,r5,#8
add r5,r5,r6,lsl#4
rsb r6,r6,r6,lsl#3
,add r4,r4,r6,lsl#2 ;r4+=r6*28
subs r2,r2,#1
bne endloop_submenu1
ldmib r5,{r6}
add r4,r4,#4
add r4,r4,r6,lsl#2
str r4,[r0,#-16]
movs pc,lr
;____________
;r8=word to be written
.putword
stmfd sp !,{r0-r4,r8,lr}
mov r0,#2
ldr r1,[r12,#desth]
add r2,sp,#5<<2
mov r3,#4
swi "XOS_GBPB"
bvs error
ldmfd sp !,{r0-r4,r8,pc}^
-; >>> EOS <<< (end of spaghetti code!)
-;________________________________________
-;________________________________________
%;r1=ptr to null terminated string
F;returns 0 in r0 if string begins with string at r1 (r0=-1 if not)
.stringstarteq
stmfd sp !,{r1-r3,lr}
ldr r2,[r12,#stringstart]
.stringstarteq1
ldrb r0,[r1],#1
teq r0,#0
7ldmeqfdsp !,{r1-r3,pc}^ ;strings are the same
ldrb r3,[r2],#1
eor r0,r0,r3
4bics r0,r0,#1<<5 ;case insensitive!
beq stringstarteq1
1mvn r0,#0 ;strings differ
ldmfd sp !,{r1-r3,pc}^
-;________________________________________
#;ignore empty and comment lines
;V set on exit if eof
.getstring
bic lr,lr,#1<<28
stmdb sp,{r0-r2,lr}
ldr r0,[r12,#sourceeof]
teq r0,#0
orrnes pc,lr,#1<<28
d("getstring")
ldr r1,[r12,#sourceh]
?.getstring1 ;loop for comment/empty lines
ldr r2,[r12,#currentline]
add r2,r2,#1
=str r2,[r12,#currentline] ;for correct error messages
swi "XOS_BGet"
bvs error
bcs getstring_eof
teq r0,#10
beq getstring1
teq r0,#
beq getstring3
add r2,r12,#string-1
strb r0,[r2,#1]!
ldr r3,[r12,#hotkey]
A.getstring2 ;loop for reading in valid line
swi "XOS_BGet"
bvs error
8strcs r12,[r12,#sourceeof] ;must just be non-zero
movcs r0,#10
strb r0,[r2,#1]!
cmp r2,r3
movhs r3,#Err_OutOfSpace
bhs report
teq r0,#10
bne getstring2
;ldr r0,[r12,#hotkey]
;cmp r2,r0
;movhs r3,#Err_OutOfSpace
;bhs report
str r2,[r12,#stringend]
add r2,r12,#string
str r2,[r12,#stringstart]
ldmdb sp,{r0-r2,pc}^
;____________
.getstring_eof
8str r12,[r12,#sourceeof] ;must just be non-zero
ldmdb sp,{r0-r2,lr}
orrs pc,lr,#1<<28
;____________
9.getstring3 ;loop for comment lines
swi "XOS_BGet"
bvs error
bcs getstring_eof
teq r0,#10
bne getstring3
b getstring1
-;________________________________________
;;insert a new menu item after last item of current menu
@;r0=ptr to current menu, r1=1st word of item (eg submenu nr)
/;r10=ptr to text, r8=ptr to byte after text
3;on exit r0=ptr to current menu, maybe shifted,
F; r1=width of menu item (System font - for pre-RISC OS 3.5)
.insertnewitem
stmfd sp !,{r2-r6,lr}
d("insertnewitem^^menu=^0^, eg submenu nr=^1^, [^10^;^8^[ text")
add r14,r12,#menu
ldmia r14,{r2,r4-r5}
&N;ensure 8 bytes too much, so menu_create needn't worry about ensuring them
add r5,r5,#16+8
(Nsubs r3,r5,r4 ;sets the flags in the same way as cmp r5,r4
)Msub r5,r5,#8 ;we don't need those 8 bytes at the moment!
ble insertnewitem1
+.sub r6,r0,r2 ;make offset
mov r0,#13
add r3,r3,#&ff
.+bic r3,r3,#&ff ;round up
/3swi "XOS_Module" ;expand RMA block
bvs error
add r4,r4,r3
25add r0,r6,r2 ;make address again
.insertnewitem1
stmia r14,{r2,r4-r5}
add r5,r2,r5
ldmib r0,{r2}
add r2,r0,r2,lsl#4
add r2,r2,#8
sub r4,r5,#16
;N.insertnewitem2 ;copy everything after current menu up by 16
teq r4,r2
ldmnedbr4!,{r3}
stmnedbr5!,{r3}
bne insertnewitem2
sub r6,r8,r10
B?cmp r6,#12 ;must new icon be indirected?
C$movle r4,#0 ;n
movle r5,#0
movle r6,#0
FOstmleiar2,{r1,r4-r6} ;if indir, store offset/-1/length, else 0/0/0
GFaddle r1,r2,#4 ;r1=destination addr for item string
ble insertnewitem4
addgt r3,r12,#indir
ldmgtiar3,{r3,r5,r7}
mov r4,r3
add r5,r3,r7
bl indirmatch
subcc r4,r5,r3
debugging%
[optp
bcs debug1
d("insertnewitem^^match at offset ^4^")
.debug1:]
:[optp
V$add r6,r6,#1 ;y
movcs r4,r7
mvn r5,#0
YCorr r1,r1,#1<<28 ;set flag to indicate indirection
ZOstmia r2,{r1,r4-r6} ;if indir, store offset/-1/length, else 0/0/0
bcc insertnewitem6
]K;the newly created item has indirected text - ensure mem in indir block
d("insertnewitem^^indirected")
add r14,r12,#indir
ldmia r14,{r2,r4-r5}
mov r1,r5
add r5,r5,r6
subs r3,r5,r4
ble insertnewitem3
stmfd sp !,{r0}
mov r0,#13
add r3,r3,#&ff
h+bic r3,r3,#&ff ;round up
i3swi "XOS_Module" ;expand RMA block
bvs error
add r4,r4,r3
ldmfd sp !,{r0}
.insertnewitem3
stmia r14,{r2,r4-r5}
oFadd r1,r2,r1 ;r1=destination addr for item string
mov r2,#0
sub r6,r6,#1
r;strb r2,[r1,r6] ;already store terminator
tO;now copy the item's string - either to 12 byte icon data or to indir block
.insertnewitem4
mov r6,r10
.insertnewitem5
x8teq r6,r8 ;don't copy terminator
ldrneb r2,[r6],#1
strneb r2,[r1],#1
bne insertnewitem5
.insertnewitem6
~Lsub r1,r8,r10 ;for pre-RO3.5 - calculate menu item width
mov r1,r1,lsl#4
add r1,r1,#12
ldmia r0,{r2-r3}
cmp r2,r1
movlt r2,r1
7add r3,r3,#1 ;increase nr of items
stmia r0,{r2-r3}
ldmfd sp !,{r2-r6,pc}^
-;________________________________________
.indirmatch
K;on entry r10=ptr to string (need not be terminated), r4=start of scan,
@; r5=end of scan=addr indirused, r6=length of string
O;on exit r5=addr of match with highest address or C set if no match found,
; r4 corrupt
P;NB this will only find ALL matches for search strings >=7 chars in length -
>;but then it's unlikely for *commands to be shorter anyway
bic lr,lr,#1<<29
!stmfd sp !,{r0-r3,r6-r12,lr}
and r6,r10,#3
mov r6,r6,lsl#3
bic r7,r10,#3
ldmia r7,{r0,r3,r8}
bic r5,r5,#3
rsb r7,r6,#32
mov r0,r0,lsr r6
orr r0,r0,r3,lsl r7
mov r3,r3,lsr r6
orr r3,r3,r8,lsl r7
mov r1,r0,lsr#8
orr r1,r1,r3,lsl#24
mov r2,r0,lsr#16
orr r2,r2,r3,lsl#16
mov r3,r3,lsl#8
orr r3,r3,r0,lsr#24
d("indirmatch^^string at ^10^, (^0^/^1^/^2^/^3^) $10^")
d("indirmatch^^string at ^10^: $10^")
.indirmatch1
ldmdb r5!,{r6-r12}
Hteq r12,r0:teqne r12,r1:teqne r12,r2:teqne r12,r3:bleq indirmatch3
Hteq r11,r0:teqne r11,r1:teqne r11,r2:teqne r11,r3:bleq indirmatch3
Hteq r10,r0:teqne r10,r1:teqne r10,r2:teqne r10,r3:bleq indirmatch3
Hteq r9,r0:teqne r9,r1:teqne r9,r2:teqne r9,r3:bleq indirmatch3
Hteq r8,r0:teqne r8,r1:teqne r8,r2:teqne r8,r3:bleq indirmatch3
Hteq r7,r0:teqne r7,r1:teqne r7,r2:teqne r7,r3:bleq indirmatch3
Hteq r6,r0:teqne r6,r1:teqne r6,r2:teqne r6,r3:bleq indirmatch3
.indirmatch2
cmp r5,r4
bhi indirmatch1
!ldmfd sp !,{r0-r3,r6-r12,lr}
orrs pc,lr,#1<<29
;____________
.indirmatch3
stmfd sp !,{r7-r12,lr}
bic lr,lr,#&FC000003
adr r12,indirmatch2
?sub r12,r12,lr ;r12 is 0/20/40/60/80/100/120
?mov r12,r12,lsr#4 ;r12 is 0/ 1/ 2/ 3/ 5/ 6/ 7
Lcmp r12,#5 ;er - not quite the way we did division in
Lsubge r12,r12,#1 ;school, but it works (only in this case!)
add r14,r5,r12,lsl#2
ldr r12,[r14]
teq r12,r0
beq indirmatch7
.indirmatch4
teq r12,r1
beq indirmatch8
.indirmatch5
teq r12,r2
beq indirmatch9
.indirmatch6
teq r12,r3
ldmnefdsp !,{r7-r12,pc}
;______
.indirmatch10
sub r11,r14,#3
@ldr r9,[sp,#7*4+4*4] ;get r6 on entry to indirmatch
Aldr r10,[sp,#7*4+8*4] ;get r10 on entry to indirmatch
.indirmatch10a
ldrb r7,[r10],#1
ldrb r8,[r11],#1
teq r7,r8
+ldmnefdsp !,{r7-r12,pc} ;no match
subs r9,r9,#1
bne indirmatch10a
Pldrb r8,[r11] ;all chars the same, now check if found string
0cmp r8,#32 ;is terminated
ldmgefdsp !,{r7-r12,pc}
8ldr r9,[sp,#7*4+4*4] ;get r6 on entry again
sub r8,r11,r9
Bcmp r8,r4 ;still above low end of scanned?
ldmlofdsp !,{r7-r12,pc}
/add sp,sp,#7*4 ;match found!
mov r5,r8
"ldmfd sp !,{r0-r3,r6-r12,pc}^
;____________
.indirmatch7
mov r11,r14
@ldr r9,[sp,#7*4+4*4] ;get r6 on entry to indirmatch
Aldr r10,[sp,#7*4+8*4] ;get r10 on entry to indirmatch
.indirmatch7a
ldrb r7,[r10],#1
ldrb r8,[r11],#1
teq r7,r8
+bne indirmatch4 ;no match
subs r9,r9,#1
bne indirmatch7a
Pldrb r8,[r11] ;all chars the same, now check if found string
0cmp r8,#32 ;is terminated
bge indirmatch4
8ldr r9,[sp,#7*4+4*4] ;get r6 on entry again
sub r8,r11,r9
Bcmp r8,r4 ;still above low end of scanned?
blo indirmatch4
/add sp,sp,#7*4 ;match found!
mov r5,r8
"ldmfd sp !,{r0-r3,r6-r12,pc}^
;____________
.indirmatch8
sub r11,r14,#1
@ldr r9,[sp,#7*4+4*4] ;get r6 on entry to indirmatch
Aldr r10,[sp,#7*4+8*4] ;get r10 on entry to indirmatch
.indirmatch8a
ldrb r7,[r10],#1
ldrb r8,[r11],#1
teq r7,r8
+bne indirmatch5 ;no match
subs r9,r9,#1
bne indirmatch8a
Pldrb r8,[r11] ;all chars the same, now check if found string
0cmp r8,#32 ;is terminated
bge indirmatch5
8ldr r9,[sp,#7*4+4*4] ;get r6 on entry again
sub r8,r11,r9
Bcmp r8,r4 ;still above low end of scanned?
blo indirmatch5
/add sp,sp,#7*4 ;match found!
mov r5,r8
"ldmfd sp !,{r0-r3,r6-r12,pc}^
;____________
.indirmatch9
sub r11,r14,#2
@ldr r9,[sp,#7*4+4*4] ;get r6 on entry to indirmatch
Aldr r10,[sp,#7*4+8*4] ;get r10 on entry to indirmatch
.indirmatch9a
ldrb r7,[r10],#1
ldrb r8,[r11],#1
teq r7,r8
+bne indirmatch6 ;no match
subs r9,r9,#1
bne indirmatch9a
Pldrb r8,[r11] ;all chars the same, now check if found string
0cmp r8,#32 ;is terminated
bge indirmatch6
!8ldr r9,[sp,#7*4+4*4] ;get r6 on entry again
sub r8,r11,r9
#Bcmp r8,r4 ;still above low end of scanned?
blo indirmatch6
%/add sp,sp,#7*4 ;match found!
mov r5,r8
'"ldmfd sp !,{r0-r3,r6-r12,pc}^
(-;________________________________________
.syntaxerror
+!mov r3,#Err_UnknownCommand
;r3=error number
.?;returns messages to make debugging of the Menu file easier
.report
mov r0,#240
mov r1,#0
mov r2,#&ff
34swi "OS_Byte" ;r1=country number
adr r4,errormessages
teq r1,#7
adreq r4,errormessages7
add r1,r12,#string
9Dorr r5,r3,#1<<30 ;set bit 30 - recommended by Acorn
stmia r1!,{r5}
; ldr r0,[r12,#currentline]
.report1
ldrb r5,[r4],#1
teq r5,#
moveq r2,#256
A6swieq "XOS_BinaryToDecimal" ;convert line number
addeq r1,r1,r2
beq report1
teq r5,#0
strneb r5,[r1],#1
bne report1
HM.report2 ;count down found 0s to find correct string
ldrb r5,[r4],#1
teq r5,#0
subeqs r3,r3,#1
bne report2
M..report3 ;copy string
ldrb r5,[r4],#1
strb r5,[r1],#1
teq r5,#0
bne report3
add r0,r12,#string
;______
.error
mov r1,r0
bl closedown
mov r0,r1
ldmfd sp !,{lr}
orrs pc,lr,#1<<28
[-;________________________________________
.closedown
bic lr,lr,#1<<28
stmfd sp !,{r0-r2,r11,lr}
mov r11,#0
ldr r1,[r12,#sourceh]
cmn r1,#1
beq closedown1
mov r0,#0
swi "XOS_Find"
movvs r11,r0
.closedown1
ldr r1,[r12,#desth]
cmn r1,#1
beq closedown2
mov r0,#0
swi "XOS_Find"
movvs r11,r0
.closedown2
mov r0,#7
ldr r2,[r12,#menu]
teq r2,#0
beq closedown3
swi "XOS_Module"
movvs r11,r0
.closedown3
ldr r2,[r12,#indir]
teq r2,#0
beq closedown4
swi "XOS_Module"
movvs r11,r0
.closedown4
teq r11,#0
ldmeqfdsp !,{r0-r2,r11,pc}^
stmfd sp,{r11}
ldmfd sp !,{r0-r2,r11,lr}
orrs pc,lr,#1<<28
-;________________________________________
.errormessages
0dcb"File
!MyMenu.Menu.Menu
, line %: ":dcb0
dcb"Syntax error":dcb0
?dcb"There must only be one character after
Special:
":dcb0
<dcb"The special character has already been defined":dcb0
8dcb"The special character has not been defined":dcb0
"dcb"The line is too long":dcb0
5dcb"Unknown modifier at the end of the line":dcb0
7dcb"Wrong
modifier at the end of the line":dcb0
7dcb"Wrong
modifier at the end of the line":dcb0
7dcb"Wrong
modifier at the end of the line":dcb0
7dcb"Wrong
modifier at the end of the line":dcb0
Kdcb"Only one item in the menu structure can have the
modifier":dcb0
Ldcb"A menu entry needs to be followed by at least one command line":dcb0
Idcb"There is a menu with no entries in it
this is not allowed":dcb0
Cdcb"No hotkeys have been defined for a menu or menu entry":dcb0
Pdcb"This command must appear before any menu or menu entry definitions":dcb0
Odcb"The hotkey specified in the
modifier has already been defined":dcb0
align
.errormessages7
2dcb"Datei
!MyMenu.Menu.Menu
, Zeile %: ":dcb0
dcb"Syntax-Fehler":dcb0
9dcb"Nach
Special:
darf nur ein Zeichen stehen":dcb0
9dcb"Das Spezial-Zeichen wurde bereits definiert":dcb0
<dcb"Das Spezial-Zeichen wurde noch nicht definiert":dcb0
#dcb"Die Zeile ist zu lang":dcb0
2dcb"Unbekannter Zusatz am Ende der Zeile":dcb0
3dcb"Falscher
-Zusatz am Ende der Zeile":dcb0
3dcb"Falscher
-Zusatz am Ende der Zeile":dcb0
3dcb"Falscher
-Zusatz am Ende der Zeile":dcb0
3dcb"Falscher
-Zusatz am Ende der Zeile":dcb0
[dcb"Nur ein Men
oder Men
eintrag des gesamten Men
s darf den
-Zusatz besitzen":dcb0
Kdcb"Auf einen Men
eintrag mu
mindestens eine Befehlszeile folgen":dcb0
Ddcb"Es gibt ein Men
ohne Eintr
das ist nicht erlaubt":dcb0
Odcb"Es wurden keinerlei Hotkeys f
r Men
s oder Men
eintr
ge definiert":dcb0
`dcb"Dieser Befehl mu
in der Datei vor Definitionen f
r Men
s oder Men
eintr
ge stehen":dcb0
Rdcb"Die im
-Zusatz genannte Tastenkombination wurde bereits definiert":dcb0
-;________________________________________
debugging%
[optp
align
debug(p,washerefile$,20):]
:[optp
]:end%=O%:[optp
rmablock(p)
-;________________________________________
]O%+=128:[optp:]:O%-=128
2)=0 A$=
i%=code%
128:$i%=A$:
"Size: ";end%-code%"/&"~end%-code%" bytes (";
((end%-code%)/102.4+.5)/10" kBytes)."'"Time: ";
/100" seconds."
"Save "+save$+" "+
~code%+" "+
~end%:
"SetType "+save$+" "+type$
REPEAT:A%=INKEY(0):MOUSEB%,B%,C%:UNTIL A%>-1ORC%>0
SYS"OS_Module",11,code%,O%-code%
rmablock(p)
P%:Otemp%=O%:[optp
-;________________________________________
;offsets in RMA block
.sourceh dcd0
.sourceeof dcd0
.desth dcd0
.currentline dcd0
*.stringstart dcd0 ;address
B.stringend dcd0 ;address of terminator of string
G.entrymenu dcd0 ;nr of menu entries will be placed in
Q.leafmenuitem dcd0 ;(address of item 4 curr. leaf submenu level)+16
@.nrofmenus dcd0 ;excluding invisible main menu
L.hotkey dcd0 ;(8 bytes each) stored downwards from +896
O.mouse dcd0 ;menu nr/item nr if MENU clicked on left side
L.osclilen dcd0 ;size of the largest non-buffered *command
L.menu dcd0 ;\ ;address of RMA block containing menu data
.menusize dcd0 ; \
<.menuused dcd0 ; \ ;nr of bytes actually used
K.indir dcd0 ;\ ;address of RMA block containing data for
E.indirsize dcd0 ; \ ; indirected icons & star commands
<.indirused dcd0 ; \ ;nr of bytes actually used
.special dcb0
.bufferallinit dcb0
P.bufferall dcb0 ;non-zero to buffer *comms of all menu entries
.ondemand dcb0
align
.var_end
.string
.rmablocksize%
-;________________________________________
rmablocksize%>1024-128
O%=Otemp%:=0
d(a$)
debugging%
[optp
bl IWasHere
dcb a$:dcb0:align:]